<?php

/**
 * 把客户端发来的密文转化成明文
 * @param $resign
 * @param $recode
 * @param $remsg
 * @return mixed
 */
function  getparmtoplain($resign, $recode, $remsg)
{
    //公私钥
    $private_key =C('private_key');
    $public_key = C('public_key');
    $private_key_pkcs8 =C('private_key_pkcs8');

    $pi_key = openssl_pkey_get_private($private_key);//这个函数可用来判断私钥是否是可用的，可用返回资源id Resource id
    $pu_key = openssl_pkey_get_public($public_key);//这个函数可用来判断公钥是否是可用的

    //解密code
    openssl_private_decrypt(base64_decode($recode), $decrypted, $pi_key);//私钥解密
    $returnrandstr = $decrypted;

    //解密msg
    $encryptedData = base64_decode($remsg);
    $decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $returnrandstr, $encryptedData, MCRYPT_MODE_CBC, $returnrandstr);

    $msgyuanwen = str_replace(array("\r\n", "\r", "\n", "\0"), "", $decrypted);

    logRes("传入密文签名sign:" . $resign . "\r\n传入密文code:" . $recode . "\r\n传入密文msg:" . $remsg . "\r\n解析后的明文：" . $msgyuanwen);

    $sign = sign($remsg, $private_key);
    $signrs = verity($remsg, $resign, $public_key);
    if (!$signrs) {
        $returnjson = '[{"sta":"0","msg":"签名验证失败服务端！"}]';
        sendtoclient($returnjson);
        die;
    }

    return $msgyuanwen;
    openssl_public_decrypt(base64_decode($resign), $decrypted, $pu_key);//私钥加密的内容通过公钥可用解密出来
}




/**
 * 把通过业务逻辑转化后的明文数据加密后返还给客户端
 * @param $returnjson
 * @param string $logname
 */
function sendtoclient($returnjson, $logname = '')
{   //公私钥
    $private_key =C('private_key');
    $public_key = C('public_key');
    $private_key_pkcs8 =C('private_key_pkcs8');

    $arr = json_decode($returnjson, 1);
    $cleanarr = null_filter($arr); //把null转化成空字符串
    $returnjson = json_encode($cleanarr);

    $content = $returnjson;
    $randstr = random(16);
    $iv = $randstr;

    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $randstr, $content, MCRYPT_MODE_CBC, $iv);
    $msg = base64_encode($encrypted);

    $pu_key = openssl_pkey_get_public($public_key);//这个函数可用来判断公钥是否是可用的
    openssl_public_encrypt($randstr, $encrypted, $pu_key);//公钥加密
    $encrypted = base64_encode($encrypted);
    $code = $encrypted;

    $pi_key = openssl_pkey_get_private($private_key);//这个函数可用来判断私钥是否是可用的，可用返回资源id Resource id
    openssl_private_encrypt($msg, $encrypted, $pi_key);//私钥加密
    $encrypted = base64_encode($encrypted);//加密后的内容通常含有特殊字符，需要编码转换下，在网络间通过url传输时要注意base64编码是否是url安全的

    $sign = sign($msg, $private_key);

    $data['msg'] = $msg;
    $data['sign'] = $sign;
    $data['code'] = $code;

    logRes("返回给客户端的明文：" . $returnjson . "\r\n返回密文签名sign:" . $sign . "\r\n返回密文code:" . $code . "\r\n返回密文msg:" . $msg);
    echo json_encode($data);
    die;
}


/**
 * 发送http的get请求
 * @param $url 请求地址
 * @return mixed
 */
function httpGet($url)
{
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_TIMEOUT, 500);
    // 为保证第三方服务器与微信服务器之间数据传输的安全性，所有微信接口采用https方式调用，必须使用下面2行代码打开ssl安全校验。
    // 如果在部署过程中代码在此处验证失败，请到 http://curl.haxx.se/ca/cacert.pem 下载新的证书判别文件。
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($curl, CURLOPT_URL, $url);
    $res = curl_exec($curl);
    curl_close($curl);
    return $res;
}


/**
 * @param $url 发送post请求的url
 * @param $data 发送的数据
 * @return mixed
 */
function curlPost($url, $data)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); //Problem (2) in the Chunked-Encoded data
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
    @curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);  //php5.6.0开始，需要加上这行代码方可上传，否则取不到文件
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $tmpInfo = curl_exec($ch);
    $errorno = curl_errno($ch);
    if ($errorno) {
        $rt['sta'] = "0";
        $rt['msg'] = "curl错误:$errorno";
        return json_encode($rt);
        die;
    }
    return $tmpInfo;
}


/**
 * 随机字符
 * @param number $length 长度
 * @param string $type 类型
 * @param number $convert 转换大小写
 * @return string
 */
function random($length = 6, $type = 'string', $convert = 0)
{
    $config = array(
        'number' => '1234567890',
        'letter' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
        'string' => 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ23456789',
        'all' => 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
    );

    if (!isset($config[$type])) $type = 'string';
    $string = $config[$type];

    $code = '';
    $strlen = strlen($string) - 1;
    for ($i = 0; $i < $length; $i++) {
        $code .= $string{mt_rand(0, $strlen)};
    }
    if (!empty($convert)) {
        $code = ($convert > 0) ? strtoupper($code) : strtolower($code);
    }
    return $code;
}


/**
 *签名数据：
 *data：utf-8编码的订单原文，
 *privatekeyFile：私钥路径
 *passphrase：私钥密码
 *返回：base64转码的签名数据
 */

function sign($data, $privatekey)
{
    $signature = '';
    $res = openssl_get_privatekey($privatekey);
    openssl_sign($data, $signature, $res);
    openssl_free_key($res);

    return base64_encode($signature);
}


/**
 * 验证签名：
 *data：原文
 *signature：签名
 *publicKeyPath：公钥路径
 *返回：签名结果，true为验签成功，false为验签失败
 */
function verity($data, $signature, $pubKey)
{
    $res = openssl_get_publickey($pubKey);
    $result = (bool)openssl_verify($data, base64_decode($signature), $res);
    openssl_free_key($res);
    return $result;
}


/**
 * 文本记录函数
 * @param string $word 输入记录的值
 */
function logRes($word = '')
{
    $logname = "./log/" . date("Ymd") . ".txt";
    $fp = fopen($logname, "a");
    flock($fp, LOCK_EX);
    fwrite($fp, "执行日期：" . strftime("%Y-%m-%d %H:%M:%S", time()) . "\r\n" . $word . "\r\n");
    flock($fp, LOCK_UN);
    fclose($fp);
}


/**
 * 过滤null 转化成 空字符串
 * @param $arr
 * @return mixed
 */
function null_filter($arr)
{
    foreach ($arr as $key => &$val) {
        if (is_array($val)) {
            $val = null_filter($val);
        } else {
            if ($val === null) {
                //unset($arr[$key]);
                $arr[$key] = '';
            }
        }
    }
    return $arr;
}





/*********以下是模拟客户端请求方法**********/

/**
 * @param $sendurl  接口url
 * @param array $sendjson 发送json数据
 * @param array $sendfile 发送的文件
 * @return mixed|string
 */
function   sendtointerface($sendurl, $sendjson = array(), $sendfile = array())
{
    //公私钥
    $private_key =C('private_key');
    $public_key = C('public_key');
    $private_key_pkcs8 =C('private_key_pkcs8');

    $content = $sendjson;
    $randstr = random(16);
    $iv = $randstr;

    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $randstr, $content, MCRYPT_MODE_CBC, $iv);
    $msg = base64_encode($encrypted);

    $pu_key = openssl_pkey_get_public($public_key);//这个函数可用来判断公钥是否是可用的
    openssl_public_encrypt($randstr, $encrypted, $pu_key);//公钥加密
    $encrypted = base64_encode($encrypted);
    $code = $encrypted;

    $pi_key = openssl_pkey_get_private($private_key);//这个函数可用来判断私钥是否是可用的，可用返回资源id Resource id
    openssl_private_encrypt($msg, $encrypted, $pi_key);//私钥加密
    $encrypted = base64_encode($encrypted);//加密后的内容通常含有特殊字符，需要编码转换下，在网络间通过url传输时要注意base64编码是否是url安全的
    $sign = $encrypted;


    $sign = sign($msg, $private_key); //签名函数
    $url = $sendurl;

    $data = $sendfile; //文件数据
    $data['msg'] = urlencode($msg);
    $data['sign'] = urlencode($sign);
    $data['code'] = urlencode($code);
    $content = curlPost($url, $data); //通过curl发送数据到接口
    $content = str_replace(array("\r\n", "\r", "\n", "\0"), "", $content); //替换掉特殊字符
    $arr = json_decode($content, 1);
    //获取接口返回的加密sign、code、msg
    $resign = $arr['sign'];
    $recode = $arr['code'];
    $remsg = $arr['msg'];


    openssl_private_decrypt(base64_decode($recode), $decrypted, $pi_key);//私钥解密
    $returnrandstr = $decrypted;

    $encryptedData = base64_decode($remsg);
    @$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $returnrandstr, $encryptedData, MCRYPT_MODE_CBC, $returnrandstr);

    $returnjson = $decrypted;
    $returnjson = str_replace(array("\r\n", "\r", "\n", "\0"), "", $returnjson);

    $sign = sign($remsg, $private_key);


    if ($sign != $resign) {
        $returnjson = '[{"sta":"0","msg":"签名验证失败客户端！"}]';
        return $returnjson;
    }

    return $returnjson;

}





